
import java.net.URI;
import java.util.Collection;
import java.util.Iterator;

import org.apache.muse.core.Environment;
import org.apache.muse.core.Resource;
import org.apache.muse.core.ResourceManager;
import org.apache.muse.core.descriptor.DeploymentDescriptor;
import org.apache.muse.core.descriptor.DescriptorConstants;
import org.apache.muse.core.descriptor.RouterDefinition;
import org.apache.muse.core.descriptor.SerializerDefinition;
import org.apache.muse.core.descriptor.SimpleDeploymentDescriptor;
import org.apache.muse.core.platform.AbstractIsolationLayer;
import org.apache.muse.core.routing.ResourceRouter;
import org.apache.muse.core.routing.SimpleResourceRouter;
import org.apache.muse.core.serializer.ArraySerializer;
import org.apache.muse.core.serializer.Serializer;
import org.apache.muse.core.serializer.SerializerRegistry;
import org.apache.muse.util.ReflectUtils;
import org.apache.muse.ws.addressing.EndpointReference;
import org.apache.muse.ws.addressing.MessageHeaders;
import org.apache.muse.ws.addressing.soap.SoapFault;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xmlpull.v1.builder.XmlBuilderException;
import org.xmlpull.v1.builder.XmlDocument;
import org.xmlpull.v1.builder.XmlElement;



import xsul.XmlConstants;
import xsul.XsulException;
import xsul.soap.SoapUtil;
import xsul.soap11_util.Soap11Util;
import xsul.soap12_util.Soap12Util;


public class WSDMProcessor{
	private ResourceRouter router;
	
	
//	
//	@Override
//	protected Environment createEnvironment() {
//		return new MyEnviorment();
//	}


	public WSDMProcessor()throws WSDMException{
		try {
			Environment env = new MyEnviorment();
			DeploymentDescriptor dd = new SimpleDeploymentDescriptor();
			
			Document ddXML = env.getDocument(DescriptorConstants.DESCRIPTOR_FILE_NAME);
			dd.load(ddXML, env);
			
			//
			// put all custom serializers in the serializer registry
			//
			Collection serializerDefinitions = dd.getSerializerDefinitions();
			Iterator i = serializerDefinitions.iterator();
			
			SerializerRegistry registry = SerializerRegistry.getInstance();
			
			while (i.hasNext())
			{
			    SerializerDefinition next = (SerializerDefinition)i.next();
			    
			    Serializer ser = next.create();
			    Class type = ser.getSerializableType();
			    
			    Class arrayType = ReflectUtils.getArrayClassFromClass(type);
			    Serializer arraySer = new ArraySerializer(arrayType, ser);
			    
			    registry.registerSerializer(type, ser);
			    registry.registerSerializer(arrayType, arraySer);
			}
			
			//
			// create the router, which will instantiate resources that 
			// are specified in the deployment descriptor (using the 
			// /muse/resource-type/@instances-at-startup attribute)
			//
			RouterDefinition routerDefinition = dd.getRouterDefinition();
			router = routerDefinition.newInstance();
			if(!router.hasBeenInitialized()){
				router.initialize();
			}
			
			
			//Either entries should be addded to router instances or add a resource manually here
			
			ResourceManager resourceManager = ((SimpleResourceRouter)router).getResourceManager();
			String resourceName = "WsResource";
			
			EndpointReference epr = new EndpointReference(new URI("http://127.0.0.1:5555"));
			Resource resource = resourceManager.getResource(epr);
			
			if(resource == null){
				resource = resourceManager.createResource(resourceName);
				resource.initialize();
				resourceManager.addResource(epr, resource);
			}
		} catch (Exception e) {
			throw new WSDMException(e);
		}
	}
	
	
	public XmlDocument processMessage(XmlElement envelope,SoapUtil soaputils)throws WSDMException{
		try {
//			if (!hasBeenInitialized()){
//	            initialize();
//	            
//			}    
			
			//ResourceRouter router = getRouter();
//			SoapUtil soaputils = SoapUtil.selectSoapFragrance(envelope, 
//					new SoapUtil[]{Soap11Util.getInstance(),Soap12Util.getInstance()});
			MyEnviorment env = (MyEnviorment)router.getEnvironment();
			
			Element domEnvelope = env.convertToDOM(envelope,soaputils);
			
			Element headers = DomUtils.getElementByName(domEnvelope,XmlConstants.S_HEADER);
			Element body = DomUtils.getElementByName(domEnvelope,XmlConstants.S_BODY);
			
			        
			if(headers != null && body != null){
			     MessageHeaders wsa = new MessageHeaders(headers);      
			     env.addAddressingContext(wsa);
			     Element soapResponse = router.invoke(body);
			     //
			     // all done - don't forget to clean up the context or 
			     // we'll have a memory leak
			     //
			     env.removeAddressingContext();
			     XmlElement response4Xsul =  env.convertToXsulXml(soapResponse);
			     return soaputils.wrapBodyContent(response4Xsul);
			}else{
				throw new WSDMException("Input message must have Headers and body, but recived  "+XmlConstants.BUILDER.serializeToString(envelope));
			}
		} catch (XsulException e) {
			throw new WSDMException(e);
		} catch (XmlBuilderException e) {
			throw new WSDMException(e);
		} catch (SoapFault e) {
			throw new WSDMException(e);
		}
	}
}
